package com.chj.classloader;

import com.sun.nio.zipfs.ZipPath;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;

/**
 *  类加载机制
 */
public class TomcatClassLoad extends ClassLoader{

    public static void main(String[] args) throws  Exception{

        //上下文类加载器 sun.misc.Launcher$AppClassLoader@18b4aac2
        System.out.println("上下文类加载器"+Thread.currentThread().getContextClassLoader());
        // null
        System.out.println("1.启动类加载器:"+ HashMap.class.getClassLoader());
        // sun.misc.Launcher$ExtClassLoader@6f94fa3e
        System.out.println("2.拓展类加载器:"+ ZipPath.class.getClassLoader());
        // sun.misc.Launcher$AppClassLoader@18b4aac2
        System.out.println("3.应用程序类加载器:"+TomcatClassLoad.class.getClassLoader());
        // 默认是通过双亲委派实现类加载机制，所以自定类首先会找父类去实现加载，因此使用的是AppClassLoader
        TomcatClassLoad tomcatClassLoad = new TomcatClassLoad(); //自定的类加载器
        Thread.currentThread().setContextClassLoader(tomcatClassLoad);

        // 这个obj对象就是通过我自己的写的类加载器,去加载的，如果不实现loadClass方法，则使用默认类加载器
        Object obj =tomcatClassLoad.loadClass("com.chj.classloader.TomcatClassLoad").newInstance();
        System.out.println("obj:"+obj.getClass().getClassLoader());
        System.out.println("这两个类是否相等:" +(obj instanceof   TomcatClassLoad) ); //是不是相等

        // 加载路径
        classpath();

    }

    /**
     * 打破双亲委派必须重写loadClass
     */
    @Override
    public final Class<?> loadClass(String name)throws ClassNotFoundException{
        try{
            // 获取编译后的class
            String filename = name.substring(name.lastIndexOf(".")+1)+".class";
            // 从class中读取字节数组
            InputStream inputStream = getClass().getResourceAsStream(filename);
            if(inputStream == null){
                return super.loadClass(name);
            }
            byte[] b = new byte[inputStream.available()];
            inputStream.read(b);
            //使用父类的方法将字节数组转换为class
            return defineClass(name,b,0,b.length);
        }catch (IOException e){
            throw new ClassNotFoundException(name);
        }
    }

    public static void classpath(){
        System.out.println("BootstrapClassLoader 的加载路径: ");
        URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
        for(URL url : urls)
            System.out.println(url);
        System.out.println("----------------------------");

        //取得扩展类加载器
        URLClassLoader extClassLoader = (URLClassLoader)ClassLoader.getSystemClassLoader().getParent();
        System.out.println(extClassLoader);
        System.out.println("扩展类加载器 的加载路径: ");
        urls = extClassLoader.getURLs();
        for(URL url : urls)
            System.out.println(url);
        System.out.println("----------------------------");

        //取得应用(系统)类加载器
        URLClassLoader appClassLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
        System.out.println(appClassLoader);
        System.out.println("应用(系统)类加载器 的加载路径: ");
        urls = appClassLoader.getURLs();
        for(URL url : urls)
            System.out.println(url);
        System.out.println("----------------------------");

    }

}
